// src/composables/useIframeMessenger.ts
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import type { Ref } from 'vue'
import { type FrameMessage, MessageType, type ThemeColor, type ConnectionState } from '@/types/iframe'

export const useIframeMessenger = (iframeRef: Ref<HTMLIFrameElement | null>) => {
  const origin = ref('')
  const handlers = reactive(new Map<MessageType, (payload: any) => void>())

  // 通信状态
  const state: ConnectionState = reactive({
    isConnected: false,
    lastMessageTime: null,
    messageCount: 0,
    activeTheme: 'gray'
  })

  // 存储可被调用的函数
  const functions = reactive(new Map<string, (...args: any[]) => any>());

  // 初始化通信
  const init = () => {
    if (typeof window === 'undefined') return

    origin.value = window.location.origin
    console.log('[Messenger] 初始化通信管理器', origin.value)

    window.addEventListener('message', handleMessage)
  }

  // 处理收到的消息
  const handleMessage = (event: MessageEvent<FrameMessage>) => {
    if (!origin.value || event.origin !== origin.value) return

    console.log('[Messenger] 收到消息:', event.data)

    state.lastMessageTime = new Date()
    state.messageCount++

    if (event.data.type === MessageType.CHILD_LOADED ||
      event.data.type === MessageType.CHILD_SDK_LOADED) {
      state.isConnected = true
      console.log('[Messenger] 子应用已加载')
    } else if (event.data.type === MessageType.CALL_FUNCTION) {
      handleFunctionCall(event.data.payload);
    }

    // 调用注册的处理函数
    const handler = handlers.get(event.data.type)
    if (handler) {
      handler(event.data.payload)
    }
  }

  // 处理函数调用请求
  const handleFunctionCall = (payload: any) => {
    const { callId, functionName, args } = payload;
    console.log(`[Messenger] 调用函数: ${functionName}`, args);

    const func = functions.get(functionName);
    if (func) {
      try {
        const result = func(...args);
        // 如果返回的是Promise，则等待结果
        if (result instanceof Promise) {
          result
            .then(res => {
              sendFunctionResult(callId, res);
            })
            .catch(error => {
              sendFunctionResult(callId, null, error.message || '调用函数出错');
            });
        } else {
          sendFunctionResult(callId, result);
        }
      } catch (error: any) {
        sendFunctionResult(callId, null, error.message || '调用函数出错');
      }
    } else {
      sendFunctionResult(callId, null, `函数 ${functionName} 未注册`);
    }
  }

  // 发送函数调用结果
  const sendFunctionResult = (callId: string, result?: any, error?: string) => {
    sendMessage(MessageType.FUNCTION_RESULT, { callId, result, error });
  }

  // 发送消息给子应用
  const sendMessage = (type: MessageType, payload?: any) => {
    if (!iframeRef.value?.contentWindow || !origin.value) {
      console.error('[Messenger] 无法发送消息: iframe未准备好')
      return
    }

    const message: FrameMessage = { type, payload }
    iframeRef.value.contentWindow.postMessage(message, origin.value)
    console.log(`[Messenger] 发送消息: ${type}`, payload)
  }

  // 设置主题
  const setTheme = (theme: ThemeColor) => {
    state.activeTheme = theme
    sendMessage(MessageType.SET_THEME, theme)
  }

  // 请求帮助
  const requestHelp = (issue: string) => {
    sendMessage(MessageType.REQUEST_HELP, issue)
  }

  // 注册消息处理器
  const onMessage = (type: MessageType, handler: (payload: any) => void) => {
    handlers.set(type, handler)
  }

  // 断开连接
  const disconnect = () => {
    window.removeEventListener('message', handleMessage)
    handlers.clear()
    state.isConnected = false
    console.log('[Messenger] 已断开连接')
  }

  // 注册函数
  const registerFunction = (name: string, func: (...args: any[]) => any) => {
    functions.set(name, func);
    console.log(`[Messenger] 注册函数: ${name}`);
  }

  // 注销函数
  const unregisterFunction = (name: string) => {
    functions.delete(name);
  }

  // 生命周期钩子
  onMounted(init)
  onBeforeUnmount(() => {
    disconnect()
  })

  return {
    sendMessage,
    setTheme,
    requestHelp,
    onMessage,
    disconnect,
    registerFunction,
    unregisterFunction,
    state
  }
}

// 全局类型扩展
declare global {
  interface Window {
    messenger: ReturnType<typeof useIframeMessenger> | undefined
  }
}

export { MessageType }
